package com.example.analysis.utils;

import java.util.Arrays;
import java.util.List;

public class EntropyWeight {
    public static double[][] calcWeight(double[][] data, List<String> processType) {
        // 消除数量级的影响
        for (int i = 0; i < data.length; i++) {
            String type = processType.get(i);
            if ("1".equals(type)) {
                ComCalcUtils.minmax(data[i]);
            } else if ("2".equals(type)) {
                ComCalcUtils.n_minmax(data[i]);
            } else if ("3".equals(type)) {
                ComCalcUtils.moderate(data[i]);
            }
        }
        // 平移
        translation(data);
        // 计算熵值
        double[] entropyArr = calcEntropy(data);
        // 计算信息效用值d
        double[] dArr = calcDifference(entropyArr);
        // 计算权重
        double[] weights = calcWeight(dArr);
        return new double[][]{entropyArr, dArr, weights};
    }

    // 平移
    private static void translation(double[][] data) {
        int m = data[0].length, n = data.length;
        for (int i = 0; i < n; i++) {
            double min = Arrays.stream(data[i]).min().orElse(0);
            for (int j = 0; j < m; j++) {
                if (data[i][j] <= 0) {
                    data[i][j] += Math.abs(min) + 0.01;
                }
            }
        }
    }

    // 计算熵值
    private static double[] calcEntropy(double[][] data) {
        double[] entropyArr = new double[data.length];
        double[][] p = new double[data.length][data[0].length];
        // 计算比重
        for (int i = 0; i < data.length; i++) {
            double sum = Arrays.stream(data[i]).sum();
            for (int j = 0; j < data[i].length; j++) {
                p[i][j] = data[i][j] / sum;
            }
        }
        // 计算熵值
        int m = p[0].length, n = p.length;
        for (int i = 0; i < n; i++) {
            double sum = 0;
            for (int j = 0; j < m; j++) {
                sum += p[i][j] * Math.log(p[i][j]);
            }
            entropyArr[i] = -(double) (1 / Math.log(m)) * sum;
        }
        return entropyArr;
    }

    // 计算信息效用
    private static double[] calcDifference(double[] entropyArr) {
        int n = entropyArr.length;
        double[] dArr = new double[n];
        for (int i = 0; i < n; i++) {
            dArr[i] = 1 - entropyArr[i];
        }
        return dArr;
    }

    // 计算权重
    private static double[] calcWeight(double[] dArr) {
        int n = dArr.length;
        double sum = Arrays.stream(dArr).sum();
        double[] weights = new double[n];
        for (int i = 0; i < n; i++) {
            weights[i] = dArr[i] / sum;
        }
        return weights;
    }
}
